package framework.util.layui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.reflectasm.MethodAccess;
import framework.util._BeanUtil;
import framework.util.layui.TreeVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 专用于对接layui的工具类
 *
 * @author 吴宇亮
 * @date 2019年1月5日
 */
public class _LayuiUtil {

	//特殊字段
	public static final String METHOD = "method";

	//分页
	/** layui分页请求参数，当前第几页**/
	public static final String PAGE = "page";
	/** layui分页请求参数，一页多少行**/
	public static final String ROWS = "rows";
	/** layui首页的页码，有些UI框架是从第0页开始的 **/
	public static int FIRST_PAGE = 1;

	//排序
	/** layui排序字段请求参数，用英文逗号或中文逗号分隔**/
	public static final String ORDER_FIELDS = "_orderFields";
	/** layui排序规则请求参数，用英文逗号或中文逗号分隔**/
	public static final String ORDER_RULES = "_orderRules";


	//具体参考https://www.layui.com/doc/modules/tree.html#data
	/** layui 构造tree组件的 <b>节点标题</b> **/
	private static final String TREE_TITLE = "title";
	/** layui 构造tree组件的 <b>节点唯一索引</b> **/
	private static final String TREE_ID = "id";
	/** layui 构造tree组件的 <b>子节点</b> **/
	private static final String TREE_CHILDREN = "children";
	/** layui 构造tree组件的 <b>点击节点弹出新窗口对应的 url。需开启 isJump 参数</b> **/
	private static final String TREE_HREF = "href";
	/** layui 构造tree组件的 <b>节点是否初始展开，默认 false</b> **/
	private static final String TREE_SPREAD = "spread";
	/** layui 构造tree组件的 <b>节点是否初始为选中状态（如果开启复选框的话），默认 false</b> **/
	private static final String TREE_CHECKED = "checked";
	/** layui 构造tree组件的 <b>节点是否为禁用状态。默认 false</b> **/
	private static final String TREE_DISABLED = "disabled";
	/** treeSelect组件的 <b>节点是否初始展开，默认 true</b> **/
	private static final String TREE_OPEN = "open";

	/** tree全部打开 **/
	private static final String TREE_SPREAD_OPENALL = "openAll";

	/**
	 * 将bo转换成Layui的tree组件所需要的格式。<br/>
	 * <b>注意：<br/>
	 * 1.要转换成tree的bo必须要有字段对id、name、children这三个进行映射，否则会抛出异常！ <br/>
	 * 2.当jsonMapping为null时，默认是如下关联 {id: 'lid', title: 'name', children: 'children'}。并且spread为true，全部展开；
     *   如果配置了，{id: 'lid', title: 'name', children: 'children', checked: '' }
	 * </b><br/>
	 * 使用示例: <br/>
	 *
	 * @param bo javabean
	 * @param jsonMapping json映射, 告诉convertToTreeVo接口, bo的什么字段对应tree的id, bo的什么字段对应tree的name
	 */
	public static<T> TreeVo convertToTreeVo(T bo, JSONObject jsonMapping) {
		Objects.requireNonNull(bo);

		//，告诉treeVo生成器，tree的字段应该从bo的哪些方法去取
		Map<String, String> methodMap = new HashMap<>(7);
		if(CollectionUtils.isEmpty(jsonMapping)){
			//当jsonMapping为null时，默认参数
			methodMap.put(TREE_TITLE, "getName");
			methodMap.put(TREE_ID, "getLid");
			methodMap.put(TREE_CHILDREN, "getChildren");
			methodMap.put(TREE_SPREAD, TREE_SPREAD_OPENALL);
			methodMap.put(TREE_OPEN, "getOpen");
		}else{
			Object title = jsonMapping.get(TREE_TITLE), id = jsonMapping.get(TREE_ID),
					children = jsonMapping.get(TREE_CHILDREN), href = jsonMapping.get(TREE_HREF),
					spread = jsonMapping.get(TREE_SPREAD), checked = jsonMapping.get(TREE_CHECKED),
					disabled = jsonMapping.get(TREE_DISABLED), open = jsonMapping.get(TREE_OPEN);
			//建立bo和tree字段之间的联系, 默认用bo的lid字段作为tree的id, name字段作为tree的显示的文字, _spread按默认layui tree组件默认的来
			methodMap.put(TREE_TITLE, null == title || StringUtils.isBlank(title.toString()) ? "getName" : _BeanUtil.getGetterMethodName(title.toString()));
			methodMap.put(TREE_ID, null == id || StringUtils.isBlank(id.toString()) ? "getLid" : _BeanUtil.getGetterMethodName(id.toString()));
			methodMap.put(TREE_CHILDREN, null == children || StringUtils.isBlank(children.toString()) ? "getChildren" : _BeanUtil.getGetterMethodName(children.toString()));
			methodMap.put(TREE_HREF, null == href || StringUtils.isBlank(href.toString()) ? null : _BeanUtil.getGetterMethodName(href.toString()));
			methodMap.put(TREE_SPREAD, null == spread || StringUtils.isBlank(spread.toString()) ? TREE_SPREAD_OPENALL : _BeanUtil.getGetterMethodName(spread.toString()));
			methodMap.put(TREE_CHECKED, null == checked || StringUtils.isBlank(checked.toString()) ? null : _BeanUtil.getGetterMethodName(checked.toString()));
			methodMap.put(TREE_DISABLED, null == disabled || StringUtils.isBlank(disabled.toString()) ? null : _BeanUtil.getGetterMethodName(disabled.toString()));
			methodMap.put(TREE_OPEN, null == open || StringUtils.isBlank(open.toString()) ? null : _BeanUtil.getGetterMethodName(open.toString()));
		}

		MethodAccess access = MethodAccess.get(bo.getClass());
		return generatorTreeVo(bo, methodMap, access);
	}

	/**
	 * TreeVo生成器
	 */
	private static<T> TreeVo generatorTreeVo(T bo, Map<String, String> methodMap, MethodAccess access) {
		TreeVo vo = new TreeVo();
		vo.setId(access.invoke(bo, methodMap.get(TREE_ID)));
		vo.setTitle(access.invoke(bo, methodMap.get(TREE_TITLE)));
		vo.setName(vo.getTitle());
		vo.setHref(null == methodMap.get(TREE_HREF) ? null : access.invoke(bo, methodMap.get(TREE_HREF)));
		vo.setSpread(TREE_SPREAD_OPENALL == methodMap.get(TREE_SPREAD) ? true : access.invoke(bo, methodMap.get(TREE_SPREAD)));
		vo.setChecked(null == methodMap.get(TREE_CHECKED) ? null : access.invoke(bo, methodMap.get(TREE_CHECKED)));
		vo.setDisabled(null == methodMap.get(TREE_DISABLED) ? null : access.invoke(bo, methodMap.get(TREE_DISABLED)));
		vo.setOpen(true);

		List<T> children = (List<T>)access.invoke(bo, methodMap.get(TREE_CHILDREN));
		if(Objects.nonNull(children)){
			List<TreeVo> treeChildren = new ArrayList<>();
			for (T child : children) {
				//递归入口
				TreeVo treeVo = generatorTreeVo(child, methodMap, access);
				treeChildren.add(treeVo);
			}
			vo.setChildren(treeChildren);
		}else{
			//递归出口
		}
		return vo;
	}
	
	/**
	 * 给定一个"时间范围字符串"，然后获取开始日期。 <br/>
	 * 如前端传来一个查询条件 q_filingDate:2018-12-31 至 2019-02-14  <br/>
	 * 
	 * @param dateRange 时间范围字符串
	 */
	public static String getStartdate(String dateRange){
		String[] dateArr = dateRange.split("至");
		if(dateArr.length >= 1){
			return dateArr[0].trim();
		}else{
			return null;
		}
	}
	
	/**
	 * 给定一个"时间范围字符串"，然后获取结束日期。 <br/>
	 * 如前端传来一个查询条件 q_filingDate:2018-12-31 至 2019-02-14  <br/>
	 * 
	 * @param dateRange 时间范围字符串
	 */
	public static String getEnddate(String dateRange){
		String[] dateArr = dateRange.split("至");
		if(dateArr.length >= 2){
			return dateArr[1].trim();
		}else{
			return null;
		}
	}
	

}
